//
// Created by Felix on 24-4-23.
//

#ifndef GAZE_APPCOMPONENT_HPP
#define GAZE_APPCOMPONENT_HPP

#include "oatpp/core/macro/component.hpp"
#include "oatpp/network/tcp/server/ConnectionProvider.hpp"
#include "oatpp/web/server/HttpConnectionHandler.hpp"
#include "oatpp/web/server/interceptor/AllowCorsGlobal.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"

#include "SwaggerComponent.hpp"
#include "DatabaseComponent.hpp"
#include "ErrorHandler.hpp"

#include "interceptor/AuthInterceptor.hpp"

class AppComponent {
public:
    SwaggerComponent swaggerComponent;
    DatabaseComponent databaseComponent;
public:
    /**
     * Create ObjectMapper component to serialize/deserialize DTOs in Contoller's API
     * 这个需要在前面
     */
    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, apiObjectMapper)([] {
        return oatpp::parser::json::mapping::ObjectMapper::createShared();
    }());
    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] {
        return oatpp::web::server::HttpRouter::createShared();
    }());
    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, serverConnectionHandler)([] {
        OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
        OATPP_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper);
        auto connectionHandler = oatpp::web::server::HttpConnectionHandler::createShared(router);
        connectionHandler->addRequestInterceptor(
                std::make_shared<oatpp::web::server::interceptor::AllowOptionsGlobal>()
        );
        connectionHandler->addResponseInterceptor(
                std::make_shared<oatpp::web::server::interceptor::AllowCorsGlobal>()
        );
        connectionHandler->addRequestInterceptor(std::make_shared<AuthInterceptor>());
        connectionHandler->setErrorHandler(std::make_shared<ErrorHandler>(objectMapper));
        return connectionHandler;
    }());
    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)([] {
        return oatpp::network::tcp::server::ConnectionProvider::createShared(
                {"0.0.0.0", 8100, oatpp::network::Address::IP_4}
                // {"::", 8100, oatpp::network::Address::IP_6}
        );
        // 这里可以编译两个文件
        // 一个使用 IP_4 配置，启动后可以通过 127.0.0.1:8100 访问
        // 一个使用 IP_6 配置，启动后可以通过 [::1]:8100 访问
        // 两个文件可以同时启动
    }());
};

#endif //GAZE_APPCOMPONENT_HPP
